package org.lmind.example.util.common;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ThreadBinder<T> {
	
	private ThreadLocal<T> local = new ThreadLocal<T>();
	
	private Class<T> interfaceClass;
	
	private T proxy;

	public void setInterfaceClass(Class<T> interfaceClass) {
		this.interfaceClass = interfaceClass;
	}
	
	public T binded() {
		return local.get();
	}

	public void bind(T value) {
		local.set(value);
	}
	
	public void unbind() {
		local.remove();
	}
	
	public T proxy() {
		return proxy(Thread.currentThread().getContextClassLoader());
	}
	
	@SuppressWarnings("unchecked")
	public T proxy(ClassLoader classLoader) {
		if (proxy == null) {
			proxy = (T) Proxy.newProxyInstance(classLoader, new Class<?>[]{interfaceClass}, new Handler());
		}
		return proxy;
	}
	
	class Handler implements InvocationHandler {

		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			T instance = local.get();
			return method.invoke(instance, args);
		}
	}
	
}
